package java_option.player.javacv.core;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber.Exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 用于从视频文件中获取音频Frame
 * 
 * @author java红了 <br/>
 *         2020-9-2819:30:45
 */
public class FrameAudioGrabberThread extends Thread {

	private static final Logger logger = LoggerFactory.getLogger(FrameAudioGrabberThread.class);

	private static FrameAudioGrabberThread instance;

	private FFmpegFrameGrabber frameGrabber;

	/**
	 * null stop, true 运行, false wait
	 */
	private Boolean isRunning = false;
	private boolean isGrabEnd = false;

	private long audioIndex;

	private FrameAudioGrabberThread() {

	}

	public static FrameAudioGrabberThread getInstance() {
		synchronized (FrameAudioGrabberThread.class) {
			if (instance == null) {
				instance = new FrameAudioGrabberThread();
			}
		}
		return instance;
	}

	public void startGrab(FFmpegFrameGrabber frameGrabber) {
		this.frameGrabber = frameGrabber;
		// 注意调用 super的start方法, 因为当前类已经重写了start
		try {
			this.frameGrabber.start();
//			frameGrabber.setTimestamp(1);// 从1开始
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 注意 在线程start之前设置
		this.isRunning = true;
		super.start();
	}

	public void waitGrab() {
		synchronized (instance) {
			try {
				instance.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void notifyGrab() {
		synchronized (instance) {
			instance.notify();
		}
	}

	@Override
	public void start() {
		throw new RuntimeException("请调用 start audio Grab(FFmpegFrameGrabber)方法 ");
	}

	@Override
		public void run() {
			while (true) {
				try {
					if (isRunning == null) {
						break;
					}
					if (isRunning.booleanValue() == false) {
						this.waitGrab();
					}
					// logger.debug("开始下一帧");
					Frame frame = frameGrabber.grabFrame();
					// logger.debug("grab ok");
					if (frame == null) {
						logger.debug("frame == null 视频结束");
						isGrabEnd = true;
						waitGrab();
						continue;
					}
					this.isGrabEnd = false;
					if (frame.samples != null) {
						audioIndex++;
						// 加入队列
						boolean isContinue = FrameFIFO.getInstance().putAudio(frame, audioIndex,frame.timestamp);
						if (isContinue == false) {
							this.waitGrab();
						}
					} else {
						// logger.debug("FrameAudioGrabberThread 出现异常");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}

			}
		}

	/**
	 * 设置播放进度
	 * 
	 * @param timestamp
	 */
	public void setTimestamp(long timestamp) {
		try {
			this.frameGrabber.setTimestamp(timestamp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void setRunning(Boolean isRunning) {
		this.isRunning = isRunning;
		if (isRunning != null && isRunning) {
			notifyGrab();
		}
		if (this.isRunning == null) {
			instance = null;
		}
	}

	public boolean isGrabEnd() {
		return this.isGrabEnd;
	}
}
